import { uctoo_user, wechatopen_users } from '../../../../prisma/generated/uctoo';
import axios from 'axios';
import { getFromCache } from '../../helpers/redis';
import * as qs from 'qs';
import { GoogleUser, UctooUser, BasicUser, WechatUser } from './uctoo_user.types';
import Cookies from 'js-cookie'

const { GOOGLE_APP_ID, GOOGLE_APP_SECRET, FRONTEND_URL } = process.env;
//#region AutoCreateCode
import {
  hideObjectKeysWithoutValues,
  hideSelectedObjectKeys,
  processIdValue,
  processIdArray,
} from '../../helpers/utilsJS';
import { deleteFromCache, setExCache } from '../../helpers/redis';
import log from "../../helpers/logger";
import { RequestParserService } from '../../lib/request-parser/src';
import { generateRowLevelPermissionFilter, checkUserHasPermission, getUserAuthorizedDataIds } from '../../helpers/permissionUtils';
import { PERMISSION_LEVEL } from '../../middlewares/auth/rowLevelPermission';
import { PrismaClient } from '../../../../prisma/generated/uctoo'

const db = new PrismaClient({
  log: ['query', 'info', 'warn', 'error'],
});

// 定义当前表的ID字段类型
const ID_FIELD_TYPE = 'uuid';

export async function createUctooUser(uctooUser) {
  try {
    uctooUser = hideSelectedObjectKeys(uctooUser, ['id']);
    const newUctooUser = await db.uctoo_user.create({
      data: {
        ...uctooUser
      },
    });
    //Cache after create
    // setExCache(newUctooUser.id, 3600, JSON.stringify(newUctooUser));
    return newUctooUser;
  } catch (e) {
    log.error(e);
    return false;
  }
}

export async function editUctooUserInDatabase(updatedUctooUser, uctooUserId, userId?) {
  try {
    const isEnabled = process.env.ROW_LEVEL_PERMISSION_ENABLED === 'true';
    
    // 如果启用了行级权限且提供了userId，检查是否有写权限
    if (isEnabled && userId) {
      const permissionResult = await checkUserHasPermission(userId, 'uctoo_user', uctooUserId, PERMISSION_LEVEL.WRITE);
      if (!permissionResult.hasPermission) {
        log.warn(`User ${userId} has no permission to edit uctoo_user ${uctooUserId}: ${permissionResult.reason}`);
        return { success: false, reason: permissionResult.reason };
      }
    }
    
    updatedUctooUser = hideSelectedObjectKeys(updatedUctooUser, ['id']);
    updatedUctooUser = hideObjectKeysWithoutValues(updatedUctooUser);
    updatedUctooUser.updated_at = new Date().toISOString(); 
    if(updatedUctooUser.deleted_at === "0"){  //recycle data
      const uctooUserFromDb = await db.uctoo_user.update({
        data: { deleted_at: { set: null } },
        where: {
          id: processIdValue(uctooUserId, ID_FIELD_TYPE),
        },
      });
      //Cache after edit
      // setExCache(uctooUserFromDb.id, 3600, JSON.stringify(uctooUserFromDb));
      if (!uctooUserFromDb) return { success: false, reason: '实体不存在' };
      return { success: true, data: uctooUserFromDb };
    }else{
      
      const uctooUserFromDb = await db.uctoo_user.update({
        data: updatedUctooUser,
        where: {
          id: processIdValue(uctooUserId, ID_FIELD_TYPE),
        },
      });
      //Cache after edit
      // setExCache(uctooUserFromDb.id, 3600, JSON.stringify(uctooUserFromDb));
      if (!uctooUserFromDb) return { success: false, reason: '实体不存在' };
      return { success: true, data: uctooUserFromDb };
    }
    
  } catch (e) {
    log.error(e);
    return { success: false, reason: '编辑实体时发生错误' };
  }
}

export async function editMultiUctooUserInDatabase(updatedUctooUser, ids, userId?) {
  try {
    const isEnabled = process.env.ROW_LEVEL_PERMISSION_ENABLED === 'true';
    
    // 如果启用了行级权限且提供了userId，检查是否对每个实体都有写权限
    if (isEnabled && userId) {
      for (const uctooUserId of ids) {
        const permissionResult = await checkUserHasPermission(userId, 'uctoo_user', uctooUserId, PERMISSION_LEVEL.WRITE);
        if (!permissionResult.hasPermission) {
          log.warn(`User ${userId} has no permission to edit uctoo_user ${uctooUserId}: ${permissionResult.reason}`);
          return { success: false, reason: permissionResult.reason, uctooUserId: uctooUserId };
        }
      }
    }
    
    updatedUctooUser = hideSelectedObjectKeys(updatedUctooUser, ['id','ids']);
    updatedUctooUser = hideObjectKeysWithoutValues(updatedUctooUser);
    updatedUctooUser.updated_at = new Date().toISOString(); 
    if(updatedUctooUser.deleted_at === "0"){  //recycle data
      const uctooUserFromDb = await db.uctoo_user.updateMany({
        data: { deleted_at: { set: null } },
        where: {
          id: {in: processIdArray(ids, ID_FIELD_TYPE)},
        },
      });
      if (!uctooUserFromDb) return { success: false, reason: '未找到要恢复的实体' };
      return { success: true, data: uctooUserFromDb };
    }else{
      const uctooUserFromDb = await db.uctoo_user.updateMany({
        data: updatedUctooUser,
        where: {
          id: {in: processIdArray(ids, ID_FIELD_TYPE)},
        },
      });
      if (!uctooUserFromDb) return { success: false, reason: '未找到要编辑的实体' };
      return { success: true, data: uctooUserFromDb };
    }
    
  } catch (e) {
    log.error(e);
    return { success: false, reason: '批量编辑实体时发生错误' };
  }
}

export async function deleteUctooUserFromDatabase(uctooUserId,force = 0, userId?) {
  try {
    const isEnabled = process.env.ROW_LEVEL_PERMISSION_ENABLED === 'true';
    
    // 如果启用了行级权限且提供了userId，检查是否有写权限
    if (isEnabled && userId) {
      const permissionResult = await checkUserHasPermission(userId, 'uctoo_user', uctooUserId, PERMISSION_LEVEL.WRITE);
      if (!permissionResult.hasPermission) {
        log.warn(`User ${userId} has no permission to delete uctoo_user ${uctooUserId}: ${permissionResult.reason}`);
        return { success: false, reason: permissionResult.reason };
      }
    }
    
    if(force){  //real delete data
      await db.uctoo_user.delete({
        where: {
          id: processIdValue(uctooUserId, ID_FIELD_TYPE),
        },
      });
    }else{  //soft delete
      await db.uctoo_user.update({
        data: {deleted_at: new Date().toISOString()},
        where: {
          id: processIdValue(uctooUserId, ID_FIELD_TYPE),
        },
      });
    }
    // deleteFromCache(uctooUserId);
    return { success: true };
  } catch (e) {
    log.error(e);
    return { success: false, reason: '删除实体时发生错误' };
  }
}

export async function deleteMultiUctooUserFromDatabase(ids,force = 0, userId?) {
  try {
    const isEnabled = process.env.ROW_LEVEL_PERMISSION_ENABLED === 'true';
    
    // 如果启用了行级权限且提供了userId，检查是否对每个实体都有写权限
    if (isEnabled && userId) {
      for (const uctooUserId of ids) {
        const permissionResult = await checkUserHasPermission(userId, 'uctoo_user', uctooUserId, PERMISSION_LEVEL.WRITE);
        if (!permissionResult.hasPermission) {
          log.warn(`User ${userId} has no permission to delete uctoo_user ${uctooUserId}: ${permissionResult.reason}`);
          return { success: false, reason: permissionResult.reason, uctooUserId: uctooUserId };
        }
      }
    }
    
    if(force){  //real delete multi data
      await db.uctoo_user.deleteMany({
        where: {
          id:{in: processIdArray(ids, ID_FIELD_TYPE)},
        },
      });
    }else{  //soft delete
      await db.uctoo_user.updateMany({
        data: {deleted_at: new Date().toISOString()},
        where: {
          id: {in: processIdArray(ids, ID_FIELD_TYPE)},
        },
      });
    }
    // deleteFromCache(uctooUserId);
    return { success: true };
  } catch (e) {
    log.error(e);
    return { success: false, reason: '批量删除实体时发生错误' };
  }
}

export async function getUctooUserFromDatabase(uctooUserId, userId?) {
  try {
    const isEnabled = process.env.ROW_LEVEL_PERMISSION_ENABLED === 'true';
    
    // 首先检查实体是否存在
    const uctooUserFromDb = await db.uctoo_user.findFirst({
      where: {
          id: processIdValue(uctooUserId, ID_FIELD_TYPE),
        },
    });
    
    // 如果实体不存在，直接返回null
    if (!uctooUserFromDb) return null;
    
    // 如果启用了行级权限且提供了userId，检查权限
    if (isEnabled && userId) {
      const hasPermission = await checkUserHasPermission(userId, 'uctoo_user', uctooUserId, PERMISSION_LEVEL.READ);
      if (!hasPermission) {
        // 用户没有权限访问此实体
        return null;
      }
    }
    
    return uctooUserFromDb;
  } catch (e) {
    log.error(e);
    return false;
  }
}

export async function getUctooUsersFromDatabase(limit, page, skip, userId?) {
  try {
    const isEnabled = process.env.ROW_LEVEL_PERMISSION_ENABLED === 'true';
    
    // 使用更明确的类型定义，允许OR属性
    const whereCondition: any = {};
    
    // 如果启用了行级权限且提供了userId，添加权限过滤
    if (isEnabled && userId) {
      // 获取用户有权访问的实体ID列表
      const authorizedIds = await getUserAuthorizedDataIds(userId, 'uctoo_user', PERMISSION_LEVEL.READ);
      
      // 组合条件：用户创建的实体 或 用户被授权访问的实体
      whereCondition.OR = [
        { creator: userId },
        { id: { in: authorizedIds } }
      ];
    }
    
    const uctooUsersFromDb = await db.uctoo_user.findMany({
      skip: limit * page + skip,
      take: limit,
      where: whereCondition
    });
    if (!uctooUsersFromDb) return null;
    return uctooUsersFromDb;
  } catch (e) {
    log.error(e);
    return false;
  }
}

export async function queryUctooUsersFromDatabase(limit, page, skip, query, userId?) {
  try {
    const requestParserService = new RequestParserService();
    const parsedQuery = requestParserService.parseQuery(query);
    // 使用any类型允许动态添加OR和AND属性
    const filter: any = parsedQuery.filter || {};
    
    const isEnabled = process.env.ROW_LEVEL_PERMISSION_ENABLED === 'true';
    
    // 如果启用了行级权限且提供了userId，添加权限过滤
    if (isEnabled && userId) {
      // 获取用户有权访问的实体ID列表
      const authorizedIds = await getUserAuthorizedDataIds(userId, 'uctoo_user', PERMISSION_LEVEL.READ);
      
      // 组合条件：原始查询条件 + (用户创建的实体 或 用户被授权访问的实体)
      const originalWhere = { ...filter };
      
      // 组合条件：用户创建的实体 或 用户被授权访问的实体
      filter.OR = [
        { creator: userId },
        { id: { in: authorizedIds } }
      ];
      
      // 如果原始查询条件不为空，将其合并到每个OR条件中
      if (Object.keys(originalWhere).length > 0) {
        filter.AND = [originalWhere];
      }
    }
    
    const uctooUsersFromDb = await db.uctoo_user.findMany({
      skip: limit * page + skip,
      take: limit,
      where: filter,
      orderBy: parsedQuery.sort,
    });
    if (!uctooUsersFromDb) return null;
    return uctooUsersFromDb;
  } catch (e) {
    log.error(e);
    return false;
  }
}

export async function countUctooUsers(userId?) {
  try {
    const isEnabled = process.env.ROW_LEVEL_PERMISSION_ENABLED === 'true';
    
    let totalCount = 0;
    
    // 如果启用了行级权限且提供了userId，使用不同的方式处理权限过滤
    if (isEnabled && userId) {
      // 获取用户有权访问的实体ID列表
      const authorizedIds = await getUserAuthorizedDataIds(userId, 'uctoo_user', PERMISSION_LEVEL.READ);
      
      // 直接在初始化时定义OR属性，避免类型错误
      const whereCondition = {
        OR: [
          { creator: userId },
          { id: { in: authorizedIds } }
        ]
      };
      
      // 计算符合条件的实体数量
      totalCount = await db.uctoo_user.count({
        where: whereCondition
      });
    } else {
      // 不启用行级权限时，直接计算所有实体数量
      totalCount = await db.uctoo_user.count();
    }
    
    return totalCount;
  } catch (e) {
    log.error(e);
    return false;
  }
}
//#endregion AutoCreateCode

interface TokenBundle {
  access_token: string;
  expires_in: number;
  refresh_token: string;
  id_token: string;
  scope: string;
}

const env = process.env.NODE_ENV;
const isDev = env === 'development';
const opts = {
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded',
  },
};

export async function getGoogleOAuthTokens(code: string): Promise<TokenBundle> {
  const url = 'https://oauth2.googleapis.com/token';

  const body = {
    code: decodeURIComponent(code),
    client_id: GOOGLE_APP_ID,
    client_secret: GOOGLE_APP_SECRET,
    redirect_uri: `${
      isDev ? 'http://localhost:4200/' : FRONTEND_URL
    }api/auth/signin/google/callback`,
    grant_type: 'authorization_code',
  };
  try {
    // 直接传递body对象，axios会自动处理x-www-form-urlencoded格式
    return axios.post(url, body, opts).then((res) => res.data as TokenBundle);
  } catch (e) {
    log.error(e);
    throw new Error(e);
  }
}

export async function getAllUserGroups(username: string) {
  return await db.uctoo_user.findUnique({
    where: {
      username,
    }
  });
}

export async function getAllUsersWithGroups() {
  return await db.uctoo_user.findMany({
    
  });
}

export async function getAllUserGroupLinks(
  username: string,
  groupname: string
) {
  return await db.link_group.findUnique({
    where: {
      owner_groupname: {
        owner: username,
        groupname,
      },
    }
  });
}

export async function getAllUsers() {
  const cachedUsers = await getFromCache('allUsers');

  if (cachedUsers) {
    return cachedUsers;
  }
  const users = await db.uctoo_user.findMany({
    select: {
      username: true,
    },
  });
  setExCache('allUsers', 3600, JSON.stringify(users));
}

export async function getGoogleUser(
  id_token: string,
  access_token: string
): Promise<GoogleUser> {
  const url = 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json';

  try {
    return axios
      .get(`${url}&access_token=${access_token}`, {
        headers: {
          Authorization: `Bearer ${id_token}`,
        },
      })
      .then((res) => res.data as GoogleUser);
  } catch (e) {
    log.error(e.response?.data?.error_description || e.message);
    throw new Error(e);
  }
}
/*
export async function getUctooUser(
    email: string,
    password: string
): Promise<BasicUser> {
  const url = 'https://javatoarktsapi.uctoo.com/api/auth/signin';

  const body = {
    email: email,
    password: password
  };
  try {
    return axios.post(url, qs.stringify(body), opts).then((res) => {
      const  headerToken = Cookies.get('access_token');
      console.log(Cookies);
      console.log('Cookies');
      console.log(res.headers["set-cookie"]);
      console.log('access_token');
      console.log(headerToken);
      res.data
    });
  } catch (e) {
    log.error(e);
    throw new Error(e);
  }
} */
/*
export const signIn = async ({ email, password }) => {
  try {
    const res = await axios.post(
        `/api/auth/signin`,
        {
          email,
          password,
        },
        { withCredentials: true }
    );
    console.log(res.data);
    return res;
  } catch (error) {
    console.log('E ' + error);
  }
};*/

export enum AuthProvider {
  Local,
  GitHub,
  Google,
  Wechat
}
export async function isEmailFree(email: string): Promise<boolean> {
 // const cachedUser = await getFromCache(email);

 // if (cachedUser) {
 //   return false;
 // } else {
  log.error('isEmailFree');
 
    const getUser = await db.uctoo_user.findUnique({
      where: {
        email:email
      },
    });
    log.error('getUser');
    log.error(getUser);
  //  setExCache(email, 3600, JSON.stringify(getUser));
    return getUser === null;
 // }
}

export async function getUserByEmail(email: string): Promise<uctoo_user> {
 // const cachedUser = await getFromCache(email);

//  if (cachedUser) {
//    return cachedUser;
 // } else {
    const user = await db.uctoo_user.findUnique({ where: { email:email } });
  //  setExCache(email, 3600, JSON.stringify(user));
    return user;
 // }
}

export async function getUserByUsername(username: string): Promise<uctoo_user> {
  // const cachedUser = await getFromCache(email);
 
 //  if (cachedUser) {
 //    return cachedUser;
  // } else {
     const user = await db.uctoo_user.findUnique({ where: { username:username } });
   //  setExCache(email, 3600, JSON.stringify(user));
     return user;
  // }
 }

export async function getWechatopenUser(openid: string): Promise<wechatopen_users> {
  const cachedUser = await getFromCache(openid);

  if (cachedUser) {
    return cachedUser;
  } else {
    const user = await db.wechatopen_users.findUnique({ where: { openid } });
    setExCache(openid, 3600, JSON.stringify(user));
    return user;
  }
}
export async function getUserById(userId: string): Promise<uctoo_user> {
  const cachedUser = false;

  if (cachedUser) {
    return cachedUser;
  } else {
    const user = await db.uctoo_user.findUnique({ where: { id: userId } });
    setExCache(userId, 3600, JSON.stringify(user));
    return user;
  }
}
export async function getWechatUserById(userId: string): Promise<wechatopen_users> {
  const cachedUser = false;

  if (cachedUser) {
    return cachedUser;
  } else {
    const user = await db.wechatopen_users.findUnique({ where: { id: userId } });
    setExCache(userId, 3600, JSON.stringify(user));
    return user;
  }
}

export async function findOrCreateUser(
  user: UctooUser,
  authProvider: AuthProvider
): Promise<uctoo_user> {
  try {
    log.error('findOrCreateUser');
      const oldUser: uctoo_user | null = await getUserByUsername(user.username);
      log.error(oldUser);
    if (!oldUser) {
      const newUser = await db.uctoo_user.create({
        data: {
          email: user.email,
          username: user.username.toLowerCase().replaceAll(' ', '-'),
          password: user.password || 'X',
          auth_provider: authProvider,
          name: user.name,
          avatar:''
        },
      });
      log.error('newUser');
      log.error(newUser);
      
  //    setExCache(newUser.id, 3600, JSON.stringify(user));
      return newUser;
    }
   // setExCache(oldUser.id, 3600, JSON.stringify(user));
    return oldUser;
    
  } catch (e) {
    throw new Error(e);
  }
}

export async function findOrCreateWechatopenUser(
  user: WechatUser,
  authProvider: AuthProvider
): Promise<wechatopen_users> {
  try {
      const oldUser: wechatopen_users | null = await getWechatopenUser(user.openid);
    if (!oldUser) {     //数据库中没有，新创建用户
      const nowTimestamp = Date.now();
      const date = new Date(nowTimestamp + Number(user.expires_in)*1000);  //access_token过期时间
      const newTokenOvertime = date.toISOString();

      const newUser = await db.wechatopen_users.upsert({
        where: {
          openid: user.openid,
        },
        update: {
          access_token: user.access_token,
        access_token_overtime: newTokenOvertime,
        refresh_token: user.refresh_token,
        scope: user.scope,
        appid: user.appid
        },
        create: {
        openid: user.openid,
        access_token: user.access_token,
        access_token_overtime: newTokenOvertime,
        refresh_token: user.refresh_token,
        scope: user.scope,
        appid: user.appid

        }
      });
   //   setExCache(newUser.id, 3600, JSON.stringify(user));
      return newUser;
    }else{   //数据库中已有，更新用户资料
      if(oldUser.unionid){   //已有用户unionid则为授权登录过的，直接返回已有用户数据，不更新资料
    //    setExCache(oldUser.id, 3600, JSON.stringify(user));
        return oldUser;

      }else{  //首次显式授权登录更新资料
        const updateUser = await db.wechatopen_users.upsert({
          where: {
            openid: user.openid,
          },
          update: {
            nickname: user.nickname,
            gender: user.gender,
            province: user.province,
            city: user.city,
            country: user.country,
            avatar_url: user.avatar_url,
            privilege: user.privilege,
            unionid: user.unionid,
            scope: user.scope
          },
          create: {
          openid: user.openid,
          nickname: user.nickname,
            gender: user.gender,
            province: user.province,
            city: user.city,
            country: user.country,
            avatar_url: user.avatar_url,
            privilege: user.privilege,
            unionid: user.unionid,
            scope: user.scope,
          appid: user.appid
  
          }
        });
    //    setExCache(updateUser.id, 3600, JSON.stringify(user));
        return updateUser;

      }
    }
    
    
  } catch (e) {
    throw new Error(e);
  }
}

export async function saveImageurlToDatabase(userId: string,imageUrl: string): Promise<uctoo_user>{
  const cachedUser = false;

  if (cachedUser) {
    return cachedUser;
  } else {
    const user = await db.uctoo_user.update({ where: { id: userId },
      data: {
        avatar: imageUrl,
      }, });
    setExCache(userId, 3600, JSON.stringify(user));
    return user;
  }

}
